﻿#include "ArenaMgr.h"
#include "CenterService.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Cache/OfflineCharacterData.h"
#include "Active/ActiveCharacter.h"
#include "Active/ActiveCharacterMgr.h"
#include "Common/Utility/ServerTime.h"
#include "base/core/random.h"
#include "Common/TableData/ArenaRobotCfg.h"
#include "MirrorMgr/MirrorMgr.h"
#include "MailCenter/MailManager.h"
#include "Duplicate/CenterDuplicateMgr.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "Common/TableData/FunctionunlockFunctionUnlockCfg.h"
#include "Common/GlobalDefine.h"
#include "Notify/CNotifyMgr.h"

ArenaMgr::ArenaMgr()
{
	m_nStartLoadTime = 0;
	m_bFinishLoad = false;
	m_lastSaveTime = 0;
	_robatConfigRanks.clear();
	_robatConfigIds.clear();
	_beChallengedMap.clear();
	memset(_rankData, 0, sizeof(_rankData));
	_ranks.clear();
	m_needSave = false;
	_mailEveryday.clear();
}

ArenaMgr::~ArenaMgr()
{
	m_nStartLoadTime = 0;
	m_bFinishLoad = false;
	m_lastSaveTime = 0;
	_robatConfigRanks.clear();
	_robatConfigIds.clear();
	_beChallengedMap.clear();
	memset(_rankData, 0, sizeof(_rankData));
	m_needSave = false;
	_mailEveryday.clear();
}

bool ArenaMgr::LoadConfig()
{
	//uint32_t rankId = 1;
	const ArenaRobotCfgMap *pCfgMap = g_GetArenaRobotCfgTable()->GetArenaRobotCfgMap();
	if (nullptr != pCfgMap)
	{
		ArenaRobotCfgMap::const_iterator iter = pCfgMap->begin();
		for (; iter != pCfgMap->end(); ++iter)
		{
			const ArenaRobotCfgInfo &info = iter->second;
			if (info.rankId > 0) //排名大于0的为竞技场，等于0的时挑战阵营首领NPC的数据
			{
				uint32_t arenaId = info.arenaId;
				_robatConfigRanks[info.rankId] = arenaId;
				_robatConfigIds[arenaId] = info.rankId;
			}
		}
	}

	return true;
}

bool ArenaMgr::Init()
{
	LoadConfig();

	bool result = false;
	bool ret = false;

	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		MMOLOG_FMT_ERROR("[center] ArenaMgr::Init....nullptr == pMessageDispatch ");
		return false;
	}
	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_ARENA, this);
	pMessageDispatch->registerClientHandler(EMODULE_ID_ARENA, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_ARENA, this);

	g_GetActiveCharacterMgr()->AddCharacterObserver(this);

	//开始加载离线数据定时器
	ret = g_GetTimerAxis()->SetTimer(TIMER_ID_StartLoad_ArenaData, 2 * 1000, this);
	MMOLOG_PROCESS_ERROR(ret);

	//启定时器，每天23点
	ret = g_GetTimerAxis()->SetFixTimer(TIMER_ID_StartSend_ArenaRewardMail, 23 * 60 * 60, 1, this);
	MMOLOG_PROCESS_ERROR(ret);

	m_lastSaveTime = Time::Now().UnixSec();

	result = true;

Exit0:
	return result;
}

bool ArenaMgr::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_ARENA);
		pMessageDispatch->unregisterClientHandler(EMODULE_ID_ARENA);
		pMessageDispatch->unregisterServerHandler(EMODULE_ID_ARENA);
	}

	g_GetActiveCharacterMgr()->RemoveCharacterObserver(this);

	g_GetTimerAxis()->KillAllTimer(this);
	g_GetTimerAxis()->KillAllFixTimer(this);

	return true;
}

void ArenaMgr::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case TIMER_ID_StartLoad_ArenaData:
	{
		if (g_GetCenterService()->IsConnectDBProxy() && g_GetOfflineCharacterDataMgr()->IsFinishLoad())
		{

			GlobalDBRequst req;
			req.set_type_id(EGlobalType_ArenFront);
			if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_GET_REQ, &req))
			{
				LogErrFmtPrint("[center] ArenaMgr load arena data...SendDataToDBProxy failed...");
			}
			else
			{
				LogDebugFmtPrint("[center] ArenaMgr start load arena data.....");
			}
			m_nStartLoadTime = g_GetGlobalServerTime()->UnixSec();
			g_GetTimerAxis()->KillTimer(TIMER_ID_StartLoad_ArenaData, this);
		}
	}
	break;
	case TIMER_ID_StartSend_ArenaRewardMail:
	{
		
		//记录这一刻玩家的排名，避免在发邮件期间玩家排名有变化
		_mailEveryday.clear();
		const ConstantConstantCfgInfo *pTax = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ArenaRewardNum);
		if (nullptr != pTax)
		{
			int32_t count = MAX_ARENA_NUM;
			if (pTax->constantdata < count)
			{
				count = pTax->constantdata;
			}
			for (int32_t i = 1; i <= count; ++i)
			{
				if (_rankData[i] > 0)
				{
					_mailEveryday[_rankData[i]] = i;
				}
			}
			LogInfoFmtPrint("[center] ArenaMgr...start send arena mail.....size:%d ", (int32_t)_mailEveryday.size());
			if (_mailEveryday.size() > 0)
			{
				SendArenaRewardMail();
			}
		}
		else
		{
			LogInfoFmtPrint("[center] ArenaMgr...start send arena mail.....nullptr = pTax, id:%d ", EArg_ArenaRewardNum);
		}
	}
	break;
	case TIMER_ID_StartLoad_ArenaRewardMailInterval:
	{
		SendArenaRewardMail();
	}
	break;
	default:
		break;
	}
}

void ArenaMgr::onClientMessage(uint32_t actionId, RECV_PACKAGE &package, uint64_t Id /* = 0 */)
{
	switch (actionId)
	{
	case CLIENT_TO_CENTER_ARENA_RANK_INFO:
	{
		OnArenaRankInfoReq(Id, package);
	}
	break;
	case CLIENT_TO_CENTER_ARENA_UPDATE_OPPONENT_INFO:
	{
		OnArenaUpdateOpponentInfoReq(Id, package);
	}
	break;
	case CLIENT_TO_CENTER_ARENA_TOP_LIST:
	{
		OnArenaTopListReq(Id, package);
	}
	break;
	default:
		break;
	}
}

void ArenaMgr::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case LOGIC_TO_CENTER_ARENA_CHALL_RESULT:
	{
		OnLogicArenaChallResult(package);
	}
	break;
	case LOGIC_TO_CENTER_ARENA_CHALL_REQ:
	{
		OnLogicArenaChallReq(package);
	}
	break;
	default:
		break;
	}
}

void ArenaMgr::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_ALL_ARENA_DATA_RSP:
	{
		//竞技场数据存储到global表里面了,不再单独存储
	}
	break;
	case DBPROXY_PROTOCOL_AREAN_LOAD_MIRROR_DATA_CALL_BACK:
	{
		OnDBLoadArenaMirrorCallBack(package);
	}
	break;
	default:
		break;
	}
}

void ArenaMgr::onCharacterDel(OfflineCharacterData *pOffLineCharacter)
{
	//如果有玩家删除角色那需要删除对应的排行信息
	CharIDType charId = pOffLineCharacter->GetCharID();
	uint32_t rankId = GetRankId(charId);
	if (rankId > MAX_ARENA_NUM || rankId <= 0)
	{
		return;
	}

	//移除排名信息
	_ranks.erase(charId);
	_rankData[rankId] = 0;
	AddNeedSave();
}
void ArenaMgr::SaveArenaData()
{
	
	//为了避免数据包太大，分两次发送
	int32_t frontSize = MAX_ARENA_NUM / 2;
	//
	ArenaMoreDBInfo moreArenaDBInfo;
	for (int32_t i = 1; i <= frontSize; ++i)
	{
		if (_rankData[i] > 0)
		{
			ArenaDBInfo *pArenaDBInfo = moreArenaDBInfo.add_info();
			if (nullptr != pArenaDBInfo)
			{
				pArenaDBInfo->set_charid(_rankData[i]);
				pArenaDBInfo->set_rankid(i);
			}			
		}
	}
	GlobalDBSetRequest req;
	req.set_type_id(EGlobalType_ArenFront);
	string strData = moreArenaDBInfo.SerializeAsString();
	req.set_data(strData);
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_SAVE_REQ, &req))
	{
		MMOLOG_FMT_ERROR("[center] ArenaMgr::SaveArenaData arena font SendSaveArenaDataToDBProxy failed...");
	}

	ArenaMoreDBInfo moreArenaDBInfoEx;
	for (uint32_t j = frontSize + 1; j <= MAX_ARENA_NUM; ++j)
	{
		if (_rankData[j] > 0)
		{
			ArenaDBInfo *pArenaDBInfo = moreArenaDBInfoEx.add_info();
			if (nullptr != pArenaDBInfo)
			{
				pArenaDBInfo->set_charid(_rankData[j]);
				pArenaDBInfo->set_rankid(j);
			}
		}
	}
	GlobalDBSetRequest reqEx;
	reqEx.set_type_id(EGlobalType_ArenBack);
	string strDataEx = moreArenaDBInfoEx.SerializeAsString();
	reqEx.set_data(strDataEx);
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_SAVE_REQ, &reqEx))
	{
		MMOLOG_FMT_ERROR("[center] ArenaMgr::SaveArenaData arena back SendSaveArenaDataToDBProxy failed...");
	}

}
void ArenaMgr::LoadArenaDataDBRet(const string &data, int32_t type)
{
	ArenaMoreDBInfo moreDBInfo;
	if (!moreDBInfo.ParseFromArray(data.c_str(), data.length()))
	{
		LogErrFmtPrint("[center] ArenaMgr::LoadArenaDataDBRet ArenaMoreDBInfo parse failed...len:%d, type:%d ",data.length(),type);
		return;
	}
	int32_t isize = moreDBInfo.info_size();
	for (int32_t i = 0; i < isize; ++i)
	{
		const ArenaDBInfo &proto = moreDBInfo.info(i);
		uint32_t rank = proto.rankid();
		CharIDType charId = proto.charid();
		if (rank > MAX_ARENA_NUM || rank <= 0)
		{
			continue;
		}
		//这里校验一次玩家,保证排名的正确性
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		if (nullptr == pOffline)
		{
			LogErrFmtPrint("[center] ArenaMgr::LoadArenaDataDBRet....nullptr == pOffline ...cid:%lu ", charId);
			continue;
		}
		//
		if (_rankData[rank] > 0)
		{
			//已经有排名了,错误
			CharIDType oldCid = _rankData[rank];
			_ranks.erase(oldCid);
			LogErrFmtPrint("[center] ArenaMgr::LoadArenaDataDBRet...cid:%lu, randk:%d,oldcid:%lu ", charId, rank, oldCid);

		}
		MAP_UINT64_UINT32::iterator iterChar = _ranks.find(charId);
		if (iterChar != _ranks.end())
		{
			//已经有排名了,错误
			uint32_t oldRank = iterChar->second;
			if (oldRank >= 1 && oldRank <= MAX_ARENA_NUM)
			{
				_rankData[oldRank] = 0;
			}

			LogErrFmtPrint("[center] ArenaMgr::LoadArenaDataDBRet...cid:%lu, randk:%d,oldrank:%lu ", charId, rank, oldRank);
		}
		_rankData[rank] = charId;
		_ranks[charId] = rank;
	}
	if (type == EGlobalType_ArenFront)
	{
		GlobalDBRequst req;
		req.set_type_id(EGlobalType_ArenBack);
		if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_GET_REQ, &req))
		{
			LogErrFmtPrint("[center] ArenaMgr load arena back data...SendDataToDBProxy failed...");
		}
		else
		{
			LogDebugFmtPrint("[center] ArenaMgr start load arena back data.....");
		}
	}
	else
	{
		m_bFinishLoad = true;
		uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
		uint64_t interSec = curTime - m_nStartLoadTime;
		LogInfoFmtPrint("[center] load arena data finished....total_count:%d ,total_sec:%lu ",(int32_t)_ranks.size(), interSec);
	}
}

//是否加载完成
bool ArenaMgr::IsFinishLoad()
{
	return m_bFinishLoad;
}

bool ArenaMgr::Update(uint64_t tick, bool isDump)
{
	_UNUSE(tick);
	uint64_t currTime = ServerTime::UnixSec();
	if (currTime >= (m_lastSaveTime + INTRAVAL_SAVE_ARENADATA) || isDump)
	{
		if (m_needSave)
		{
			SaveArenaData();
			m_lastSaveTime = currTime;
			m_needSave = false;
		}
	}

	return true;
}

//DB 和中心服断开连接
void ArenaMgr::OnDBDisconnect()
{
	//DB 和中心服断开连接 需要清除掉正在向DB请求玩家镜像数据 的挑战状态，不然会导致后续无法挑战竞技场了
	InArenaBeChallengedMap::iterator iterChall = _beChallengedMap.begin();
	while (iterChall != _beChallengedMap.end())
	{
		if (AREA_CHALL_STATE_DB_MIRROR == iterChall->second)
		{
			iterChall = _beChallengedMap.erase(iterChall);
			continue;
		}
		++iterChall;
	}
}

bool ArenaMgr::OnArenaRankInfoReq(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWArenaRankInfoReq arenaRankInfoReq;
	ProtoBuf::WCArenaRankInfoRsp arenaRankInfoRsp;

	if (!arenaRankInfoReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWArenaRankInfoReq parse failed...");
		return false;
	}

	ActiveCharacter *pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		arenaRankInfoRsp.set_ret(RET_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_RANK_INFO, &arenaRankInfoRsp);
		return false;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		arenaRankInfoRsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_RANK_INFO, &arenaRankInfoRsp);
		return false;
	}

	const FunctionunlockFunctionUnlockCfgInfo *pLockCfg = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ARENA);
	if (nullptr != pLockCfg && pOffline->GetLevel() < pLockCfg->unlockLevel)
	{
		arenaRankInfoRsp.set_ret(RET_LEVEL_LACK);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_RANK_INFO, &arenaRankInfoRsp);
		return false;
	}

	uint32_t rankId = GetRankId(charId);
	arenaRankInfoRsp.set_rankid(rankId);
	arenaRankInfoRsp.set_charid(charId);

	uint32_t ids[ARENA_CHALL_LIST_NUM] = {0};
	GetCanChallRank(rankId, ids);
	for (uint32_t i = 0; i < ARENA_CHALL_LIST_NUM; i++)
	{
		uint32_t tmpRank = ids[i];
		//如果是排名大于MAX_ARENA_NUM则认为是错误了
		if (tmpRank > MAX_ARENA_NUM || tmpRank <= 0)
		{
			continue;
		}

		//如果这里获取的角色ID是0 那么需要补充机器人 _rankData的索引是实际排行ID
		CharIDType tmpCharId = _rankData[tmpRank];
		if (tmpCharId == 0)
		{
			uint32_t robotId = GetRobotId(tmpRank);
			if (robotId > 0)
			{
				const ArenaRobotCfgInfo *robotCfgInfo = g_GetArenaRobotCfgTable()->GetArenaRobotCfgInfo(robotId);
				if (nullptr != robotCfgInfo)
				{
					ArenaRankInfo *arenaRankInfo = arenaRankInfoRsp.add_arenarankinfo();
					arenaRankInfo->set_rankid(tmpRank);
					arenaRankInfo->set_dstid(robotId);
					arenaRankInfo->set_dstname(robotCfgInfo->robotname);
					arenaRankInfo->set_lv(robotCfgInfo->robotLv);
					arenaRankInfo->set_type(ARENA_CHALLENGE_TYPE_ROBOT);
				}
			}
		}
		else
		{
			//真实玩家的情况
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(tmpCharId);
			if (nullptr != pOffline)
			{
				ArenaRankInfo *arenaRankInfo = arenaRankInfoRsp.add_arenarankinfo();
				arenaRankInfo->set_rankid(tmpRank);
				arenaRankInfo->set_dstid(tmpCharId);
				arenaRankInfo->set_dstname(pOffline->GetCharName());
				arenaRankInfo->set_lv(pOffline->GetLevel());
				arenaRankInfo->set_fight(pOffline->GetFight());
				arenaRankInfo->set_type(ARENA_CHALLENGE_TYPE_CHARACTER);
				arenaRankInfo->set_sex(pOffline->GetSex());
				arenaRankInfo->set_prof(pOffline->GetProf());
				arenaRankInfo->mutable_facade()->CopyFrom(pOffline->GetFacade());
			}
		}
	}

	//转发到逻辑服去
	g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_ARENA, CENTER_TO_LOGIC_ARENA_RANK_INFO, &arenaRankInfoRsp);

	return true;
}

bool ArenaMgr::OnArenaUpdateOpponentInfoReq(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWArenaUpdateOpponentInfoReq req;
	ProtoBuf::WCArenaUpdateOpponentInfoRsp rsp;

	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWArenaUpdateOpponentInfoReq parse failed...");
		return false;
	}

	ActiveCharacter *pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		rsp.set_ret(RET_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_UPDATE_OPPONENT_INFO, &rsp);
		return false;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_UPDATE_OPPONENT_INFO, &rsp);
		return false;
	}
	const FunctionunlockFunctionUnlockCfgInfo *pLockCfg = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ARENA);
	if (nullptr != pLockCfg && pOffline->GetLevel() < pLockCfg->unlockLevel)
	{
		rsp.set_ret(RET_LEVEL_LACK);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_UPDATE_OPPONENT_INFO, &rsp);
		return false;
	}

	uint32_t rankId = GetRankId(charId);

	uint32_t ids[ARENA_CHALL_LIST_NUM] = {0};
	GetCanChallRank(rankId, ids);
	for (uint32_t i = 0; i < ARENA_CHALL_LIST_NUM; i++)
	{
		uint32_t tmpRank = ids[i];
		//如果是排名大于MAX_ARENA_NUM则认为是错误了
		if (tmpRank > MAX_ARENA_NUM || tmpRank <= 0)
		{
			continue;
		}
		CharIDType tmpCharId = _rankData[tmpRank];
		//如果这里获取的角色ID是0 那么需要补充机器人
		if (tmpCharId == 0)
		{
			uint32_t robotId = GetRobotId(tmpRank);
			if (robotId > 0)
			{
				const ArenaRobotCfgInfo *robotCfgInfo = g_GetArenaRobotCfgTable()->GetArenaRobotCfgInfo(robotId);
				if (nullptr != robotCfgInfo)
				{
					ArenaRankInfo *arenaRankInfo = rsp.add_arenarankinfo();
					arenaRankInfo->set_rankid(tmpRank);
					arenaRankInfo->set_dstid(robotId);
					arenaRankInfo->set_dstname(robotCfgInfo->robotname);
					arenaRankInfo->set_lv(robotCfgInfo->robotLv);
					arenaRankInfo->set_type(ARENA_CHALLENGE_TYPE_ROBOT);
				}
			}
		}
		else
		{
			//真实玩家的情况
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(tmpCharId);
			if (nullptr != pOffline)
			{
				ArenaRankInfo *arenaRankInfo = rsp.add_arenarankinfo();
				arenaRankInfo->set_rankid(tmpRank);
				arenaRankInfo->set_dstid(tmpCharId);
				arenaRankInfo->set_dstname(pOffline->GetCharName());
				arenaRankInfo->set_lv(pOffline->GetLevel());
				arenaRankInfo->set_fight(pOffline->GetFight());
				arenaRankInfo->set_type(ARENA_CHALLENGE_TYPE_CHARACTER);
				arenaRankInfo->set_sex(pOffline->GetSex());
				arenaRankInfo->set_prof(pOffline->GetProf());
				arenaRankInfo->mutable_facade()->CopyFrom(pOffline->GetFacade());
			}
		}
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_UPDATE_OPPONENT_INFO, &rsp);

	return true;
}

bool ArenaMgr::OnArenaTopListReq(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWArenaTopListReq req;
	ProtoBuf::WCArenaTopListRsp rsp;

	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWArenaTopListReq parse failed...");
		return false;
	}

	ActiveCharacter *pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		rsp.set_ret(RET_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_TOP_LIST, &rsp);
		return false;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_TOP_LIST, &rsp);
		return false;
	}
	const FunctionunlockFunctionUnlockCfgInfo *pLockCfg = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ARENA);
	if (nullptr != pLockCfg && pOffline->GetLevel() < pLockCfg->unlockLevel)
	{
		rsp.set_ret(RET_LEVEL_LACK);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_TOP_LIST, &rsp);
		return false;
	}

	for (uint32_t i = 1; i <= ARENA_TOP_LIST_NUM; i++)
	{
		//如果该位置没有人 那么填充机器人
		CharIDType charId = _rankData[i];
		int32_t rank = i;
		if (charId == 0)
		{
			uint32_t robotId = GetRobotId(rank);
			if (robotId > 0)
			{
				const ArenaRobotCfgInfo *robotCfgInfo = g_GetArenaRobotCfgTable()->GetArenaRobotCfgInfo(robotId);
				if (nullptr != robotCfgInfo)
				{
					ArenaRankInfo *arenaRankInfo = rsp.add_arenarankinfo();
					arenaRankInfo->set_rankid(rank);
					arenaRankInfo->set_dstid(robotId);
					arenaRankInfo->set_dstname(robotCfgInfo->robotname);
					arenaRankInfo->set_lv(robotCfgInfo->robotLv);
					arenaRankInfo->set_type(ARENA_CHALLENGE_TYPE_ROBOT);
				}
			}
		}
		else
		{
			//真实玩家的情况
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
			if (nullptr != pOffline)
			{
				ArenaRankInfo *arenaRankInfo = rsp.add_arenarankinfo();
				arenaRankInfo->set_rankid(rank);
				arenaRankInfo->set_dstid(charId);
				arenaRankInfo->set_dstname(pOffline->GetCharName());
				arenaRankInfo->set_lv(pOffline->GetLevel());
				arenaRankInfo->set_fight(pOffline->GetFight());
				arenaRankInfo->set_type(ARENA_CHALLENGE_TYPE_CHARACTER);
				arenaRankInfo->set_sex(pOffline->GetSex());
				arenaRankInfo->set_prof(pOffline->GetProf());
				arenaRankInfo->mutable_facade()->CopyFrom(pOffline->GetFacade());
			}
		}
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_TOP_LIST, &rsp);

	return true;
}

void ArenaMgr::GetArenaRankList(std::vector<ArenaRankInfo> &rankList)
{
	for (uint32_t i = 1; i <= MAX_ARENA_RANK_NUM; i++)
	{
		//如果该位置没有人 那么填充机器人
		CharIDType charId = _rankData[i];
		int32_t rank = i;
		if (charId == 0)
		{
			uint32_t robotId = GetRobotId(rank);
			if (robotId > 0)
			{
				const ArenaRobotCfgInfo *robotCfgInfo = g_GetArenaRobotCfgTable()->GetArenaRobotCfgInfo(robotId);
				if (nullptr != robotCfgInfo)
				{
					ArenaRankInfo arenaRankInfo;
					arenaRankInfo.set_rankid(rank);
					arenaRankInfo.set_dstid(robotId);
					arenaRankInfo.set_dstname(robotCfgInfo->robotname);
					arenaRankInfo.set_lv(robotCfgInfo->robotLv);
					arenaRankInfo.set_type(ARENA_CHALLENGE_TYPE_ROBOT);
					arenaRankInfo.set_prof(robotCfgInfo->robotProfession);
					arenaRankInfo.set_fight(robotCfgInfo->sword);
					rankList.push_back(arenaRankInfo);
				}
			}
		}
		else
		{
			//真实玩家的情况
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
			if (nullptr != pOffline)
			{
				ArenaRankInfo arenaRankInfo;
				arenaRankInfo.set_rankid(rank);
				arenaRankInfo.set_dstid(charId);
				arenaRankInfo.set_dstname(pOffline->GetCharName());
				arenaRankInfo.set_lv(pOffline->GetLevel());
				arenaRankInfo.set_fight(pOffline->GetFight());
				arenaRankInfo.set_type(ARENA_CHALLENGE_TYPE_CHARACTER);
				arenaRankInfo.set_sex(pOffline->GetSex());
				arenaRankInfo.set_prof(pOffline->GetProf());
				arenaRankInfo.mutable_facade()->CopyFrom(pOffline->GetFacade());
				rankList.push_back(arenaRankInfo);
			}
		}
	}
}

bool ArenaMgr::IsInArena(CharIDType charId, ARENA_CHALLENGE_TYPE type)
{
	InArenaBeChallenged beChallenged;
	beChallenged.dstId = charId;
	beChallenged.type = type;
	InArenaBeChallengedMap::iterator iter = _beChallengedMap.find(beChallenged);
	if (iter != _beChallengedMap.end())
	{
		return true;
	}

	return false;
}

bool ArenaMgr::OnLogicArenaChallReq(RECV_PACKAGE &package)
{
	GWArenaChallReq req;
	ProtoBuf::WCArenaChallRsp rsp;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[center] ArenaMgr::OnLogicArenaChallReq GWArenaChallReq parse failed...");
		return false;
	}
	CharIDType charId = req.srcid();
	int32_t rankId = req.rankid();
	CharIDType dstId = req.dstid();
	uint32_t type = req.type();

	ActiveCharacter *pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return false;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}

	//被挑战方的排名不可能是大于5000名的
	uint32_t challRankId = 0;
	if (type == ARENA_CHALLENGE_TYPE_ROBOT)
	{
		challRankId = GetRobotRankId(dstId);
	}
	else
	{
		//判断一下有没有该玩家
		OfflineCharacterData *pDstOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstId);
		if (nullptr == pDstOffline)
		{
			rsp.set_ret(RET_FAIL);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
			return false;
		}
		challRankId = GetRankId(dstId);
	}

	if (challRankId > MAX_ARENA_NUM || challRankId <= 0)
	{
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}

	//检测被挑战方的排行有没有发生改变了
	if (rankId != (int32_t)challRankId)
	{
		rsp.set_ret(RET_ARENA_CAN_NOT_CHALL_RANK_CHANGE);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}

	//检查挑战的排名是否符合
	if (!CanChall(charId, challRankId))
	{
		rsp.set_ret(RET_ARENA_CAN_NOT_CHALL_DST);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}

	//检测客户端有么有胡乱发挑战的类型
	if ((type == ARENA_CHALLENGE_TYPE_ROBOT && _rankData[challRankId] != 0) ||
		(type == ARENA_CHALLENGE_TYPE_CHARACTER && _rankData[challRankId] == 0))
	{
		//如果客户端发送上来是要挑战机器人但是该位置站的确是玩家则认为客户端发来的指令有错误
		rsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}

	//判断挑战方是否已经在挑战竞技场中
	if (IsInArena(charId))
	{
		rsp.set_ret(RET_ARENA_IN_CHALLING);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}

	//检测被挑战方是否被挑战中
	if (IsInArena(dstId, (ARENA_CHALLENGE_TYPE)type))
	{
		rsp.set_ret(RET_ARENA_CAN_NOT_CHALL_DST_IN_BECHALL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);
		return false;
	}
	int32_t challType = AREA_CHALL_STATE_NONE;
	//如果是机器人加载机器人的镜像数据
	if (type == ARENA_CHALLENGE_TYPE_ROBOT)
	{
		CharacterMirrorData mirrorData;
		mirrorData.set_charid(dstId);
		mirrorData.set_type(type);
		if (RET_SUCCESS != g_GetCenterDuplicateMgr()->enterArenaDup(charId, mirrorData))
		{
			LogErrFmtPrint("[center] OnLogicArenaChallReq...enterArenaDup failed...srcid:%lu, dstid:%lu, rankid:%d, type:%d ", charId, dstId, rankId, type);
			return false;
		}
		else
		{
			challType = AREA_CHALL_STATE_ROBOT;
		}
	}
	else
	{
		//如果是真实玩家先从镜像缓存中查找
		MirrorRole *pMirrorRole = g_GetMirrorMgr()->Get(dstId);
		if (pMirrorRole != nullptr)
		{
			//如果镜像缓存中存在那么直接将数据打包传给副本
			CharacterMirrorData *pMirrorData = pMirrorRole->Get();
			if (pMirrorData != nullptr)
			{
				pMirrorData->set_type(type);
				if (RET_SUCCESS != g_GetCenterDuplicateMgr()->enterArenaDup(charId, *pMirrorData))
				{
					LogErrFmtPrint("[center] OnLogicArenaChallReq11...enterArenaDup failed...srcid:%lu, dstid:%lu, rankid:%d, type:%d ", charId, dstId, rankId, type);
					return false;
				}
				else
				{
					challType = AREA_CHALL_STATE_MIRROR;
				}
			}
			else
			{
				LogErrFmtPrint("[center] OnLogicArenaChallReq12...pMirrorData is null ..srcid:%lu, dstid:%lu, rankid:%d, type:%d ", charId, dstId, rankId, type);
				return false;
			}
		}
		else
		{
			//如果没有请求DB加载镜像数据
			ProtoBuf::AreanLoadMirrorDataCallBack callBack;
			callBack.set_charid(charId);
			callBack.set_dstid(dstId);
			//交给系统管理器去负责加载镜像数据
			if (!g_GetMirrorMgr()->LoadCharacterMirrorData(dstId, EMODULE_ID_ARENA, DBPROXY_PROTOCOL_AREAN_LOAD_MIRROR_DATA_CALL_BACK, &callBack))
			{
				LogErrFmtPrint("[center] OnLogicArenaChallReq...LoadCharacterMirrorData failed...srcid:%lu, dstid:%lu, rankid:%d, type:%d ", charId, dstId, rankId, type);
				return false;
			}
			else
			{
				challType = AREA_CHALL_STATE_DB_MIRROR;
			}
		}
	}
	if (AREA_CHALL_STATE_NONE != challType)
	{
		//锁定被挑战方
		InArenaBeChallenged beChallenged;
		beChallenged.dstId = dstId;
		beChallenged.type = (ARENA_CHALLENGE_TYPE)type;
		//如果没有被挑战那么此时要设置被挑战状态
		_beChallengedMap[beChallenged] = challType;

		//锁定挑战方
		InArenaBeChallenged challenge;
		challenge.dstId = charId;
		challenge.type = ARENA_CHALLENGE_TYPE_CHARACTER;
		_beChallengedMap[challenge] = challType;
	}

	return true;
}

bool ArenaMgr::OnLogicArenaChallResult(RECV_PACKAGE &package)
{
	ProtoBuf::GWArenaChallResult req;
	ProtoBuf::WCArenaChallResult rsp;

	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[center] ArenaMgr::OnLogicArenaChallResult GWArenaChallResult parse failed...");
		return false;
	}

	CharIDType srcId = req.srccharid();
	CharIDType dstId = req.dstcharid();
	uint32_t addScore = req.srcscore();
	ARENA_CHALLENGE_TYPE type = (ARENA_CHALLENGE_TYPE)req.type();
	//uint32_t historyRankId = req.historyrankid();

	MMOLOG_FMT_INFO("ArenaMgr::OnLogicArenaChallResult srcId=%lu to result dstId=%lu dstType%d, result:%d, addScore:%d  ", srcId, dstId, type, req.ret(), addScore);

	//挑战方胜利了
	if (req.ret() == ACRE_WIN)
	{
		int32_t oldRank = GetRankId(srcId);
		bool isSendMail = ChangeChallRank(srcId, dstId, type);
		//isSendMail为true表示排名发生的变化
		if (isSendMail)
		{
			//发送邮件给被挑战方
			if (type == ARENA_CHALLENGE_TYPE_CHARACTER)
			{
				SendArenaLoseMail(srcId, dstId);
			}
		}
		//排名提升
		int32_t newRank = GetRankId(srcId);
		if (newRank < oldRank)
		{
			GWArenaRankChangeNotify notify;
			notify.set_charid(srcId);
			notify.set_rank(newRank);
			g_GetCenterService()->SendDataToLogicByCharID(srcId, EMODULE_ID_ARENA, CENTER_TO_LOGIC_ARENA_RANK_CHANGE, &notify);
		}
		//竞技场排名改变
		if (oldRank != newRank)
		{
			g_GetCNotifyMgr()->OnArenaRankChange(srcId, newRank);
		}


		//排名发生改变了 需要奖励金钱
		//int32_t addDiamond = 0;
		//uint32_t newSrcRankId = GetRankId(srcId);
		//if (newSrcRankId < historyRankId)
		//{
		//	addDiamond = GetBestReward(historyRankId, newSrcRankId);
		//	//发送到逻辑服增加钻石
		//	WGArenaAddDiamond addDiamondReq;
		//	addDiamondReq.set_adddiamond(addDiamond);
		//	addDiamondReq.set_historyrankdid(newSrcRankId);
		//	addDiamondReq.set_charid(srcId);
		//	g_GetCenterService()->SendDataToLogicByCharID(srcId, EMODULE_ID_ARENA, CENTER_TO_LOGIC_ARENA_ADD_DIAMOND, &addDiamondReq);
		//}

		//发送给挑战方
		rsp.set_ret(ACRE_WIN);
		rsp.set_rankid(newRank);
		rsp.set_score(addScore);
		//rsp.set_diamond(addDiamond);
		g_GetCenterService()->SendDataToClient(srcId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL_RESULT, &rsp);

		/*	if (type == ARENA_CHALLENGE_TYPE_CHARACTER)
		{
			uint32_t dstRankId = GetRankId(dstId);
			rsp.set_ret(ACRE_LOSE);
			rsp.set_rankid(GetRankId(dstRankId));
			rsp.set_score(ARENA_ADD_SCORE_LOSE);
			g_GetCenterService()->SendDataToClient(dstId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL_RESULT, &rsp);
		}*/
	}
	else
	{
		if (type == ARENA_CHALLENGE_TYPE_CHARACTER)
		{
			SendArenaWinMail(srcId, dstId);
		}

		//发送给被挑战方
		/*if (type == ARENA_CHALLENGE_TYPE_CHARACTER)
		{
			uint32_t dstRankId = GetRankId(dstId);
			rsp.set_ret(ACRE_WIN);
			rsp.set_rankid(GetRankId(dstRankId));
			rsp.set_score(ARENA_ADD_SCORE_WIN);
			g_GetCenterService()->SendDataToClient(dstId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL_RESULT, &rsp);
		}*/

		rsp.set_ret(ACRE_LOSE);
		rsp.set_rankid(GetRankId(srcId));
		rsp.set_score(addScore);
		g_GetCenterService()->SendDataToClient(srcId, EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL_RESULT, &rsp);
	}

	//取消挑战状态
	RemoveBeChallenged(dstId, type);
	RemoveBeChallenged(srcId);
	return true;
}

void ArenaMgr::OnDBLoadArenaMirrorCallBack(RECV_PACKAGE &package)
{
	AreanLoadMirrorDataCallBack callBack;
	if (!callBack.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[center] ArenaMgr::OnDBLoadArenaMirrorCallBack AreanLoadMirrorDataCallBack parse failed...");
		return;
	}

	CharIDType charId = callBack.charid();
	CharIDType dstId = callBack.dstid();
	if (!IsInArena(charId) || !IsInArena(dstId)) //这里校验是否再挑战中
	{
		//取消被挑战状态
		RemoveBeChallenged(dstId, ARENA_CHALLENGE_TYPE_CHARACTER);
		RemoveBeChallenged(charId);
		LogErrFmtPrint("[center] OnDBLoadArenaMirrorCallBack.....!IsInArena(charId) || !IsInArena(dstId)....charid:%lu, dstid:%lu ", charId, dstId);
		return;
	}
	ActiveCharacter *pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		//取消被挑战状态
		RemoveBeChallenged(dstId, ARENA_CHALLENGE_TYPE_CHARACTER);
		RemoveBeChallenged(charId);
		return;
	}

	//再次去查找缓存中是否有镜像数据
	MirrorRole *pMirrorRole = g_GetMirrorMgr()->Get(dstId);
	if (nullptr == pMirrorRole)
	{
		//这里查找不到有可能是角色删角色了
		RemoveBeChallenged(dstId, ARENA_CHALLENGE_TYPE_CHARACTER);
		RemoveBeChallenged(charId);
		return;
	}

	//成功的话那么直接将数据打包传给副本
	if (g_GetCenterDuplicateMgr()->canEnterArenaDup(charId) != RET_SUCCESS)
	{
		RemoveBeChallenged(dstId, ARENA_CHALLENGE_TYPE_CHARACTER);
		RemoveBeChallenged(charId);
		return;
	}

	CharacterMirrorData *pMirrorData = pMirrorRole->Get();
	if (nullptr == pMirrorData)
	{
		RemoveBeChallenged(dstId, ARENA_CHALLENGE_TYPE_CHARACTER);
		RemoveBeChallenged(charId);
		return;
	}

	pMirrorData->set_type(ARENA_CHALLENGE_TYPE_CHARACTER);
	if (RET_SUCCESS == g_GetCenterDuplicateMgr()->enterArenaDup(charId, *pMirrorData))
	{
		//成功，修改下挑战状态 从 AREA_CHALL_TYPE_DB_MIRROR 到 AREA_CHALL_TYPE_MIRROR
		//避免DB和中心服断开之后把这个挑战状态清除掉了

		//锁定被挑战方
		InArenaBeChallenged beChallenged;
		beChallenged.dstId = dstId;
		beChallenged.type = ARENA_CHALLENGE_TYPE_CHARACTER;
		//如果没有被挑战那么此时要设置被挑战状态
		_beChallengedMap[beChallenged] = AREA_CHALL_STATE_MIRROR;

		//锁定挑战方
		InArenaBeChallenged challenge;
		challenge.dstId = charId;
		challenge.type = ARENA_CHALLENGE_TYPE_CHARACTER;
		_beChallengedMap[challenge] = AREA_CHALL_STATE_MIRROR;

		return;
	}
	else
	{
		//取消被挑战状态
		RemoveBeChallenged(dstId, ARENA_CHALLENGE_TYPE_CHARACTER);
		RemoveBeChallenged(charId);
		return;
	}
}

void ArenaMgr::GetCanChallRank(int32_t myRankId, uint32_t ids[ARENA_CHALL_LIST_NUM])
{
	int32_t maxRankId = 0;
	int32_t minRankId = 0;

	if (myRankId >= 1 && myRankId <= 9)
	{
		int32_t intervalRankId = myRankId - 5;
		minRankId = intervalRankId <= 0 ? 1 : myRankId - 5;
		maxRankId = myRankId + 10;
	}

	else if (myRankId >= 10 && myRankId <= 19)
	{
		minRankId = myRankId - 5;
		maxRankId = myRankId + 10;
	}

	else if (myRankId >= 20 && myRankId <= 49)
	{
		minRankId = myRankId - 10;
		maxRankId = myRankId + 10;
	}

	else if (myRankId >= 50 && myRankId <= 99)
	{
		minRankId = myRankId - 30;
		maxRankId = myRankId + 20;
	}

	else if (myRankId >= 100 && myRankId <= 199)
	{
		minRankId = myRankId - 50;
		maxRankId = myRankId + 30;
	}

	else if (myRankId >= 200 && myRankId <= 499)
	{
		minRankId = myRankId - 100;
		maxRankId = myRankId + 50;
	}

	if (myRankId >= 500 && myRankId <= 999)
	{
		minRankId = myRankId - 300;
		maxRankId = myRankId + 100;
	}

	if (myRankId >= 1000 && myRankId <= 1999)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId + 200;
	}

	if (myRankId >= 2000 && myRankId <= 2999)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId;
	}

	if (myRankId >= 3000 && myRankId <= 3999)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId;
	}

	if (myRankId >= 4000 && myRankId <= 5000)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId;
	}

	if (myRankId > 5000)
	{
		minRankId = MAX_ARENA_NUM - 1000;
		maxRankId = MAX_ARENA_NUM;
	}
	int32_t tmp = 0;
	if (myRankId >= minRankId && myRankId <= maxRankId)
	{
		tmp = 1;
	}
	int32_t rescount = maxRankId - minRankId - tmp;
	if ((uint32_t)rescount < ARENA_CHALL_LIST_NUM)
	{
		LogErrFmtPrint("ArenaMgr::GetCanChallRank....rescount < ARENA_CHALL_LIST_NUM...myrank:%d , minrank:%d, maxrank:%d ", myRankId, minRankId, maxRankId);
		return;
	}
	VEC_INT32 vecRank;
	vecRank.clear();
	for (int32_t i = minRankId; i <= maxRankId; ++i)
	{
		if (i != myRankId )
		{
			vecRank.push_back(i);
		}
	}
	int32_t isize = vecRank.size();
	for (uint32_t j = 0; j < ARENA_CHALL_LIST_NUM; ++j)
	{
		int32_t idx = Random(isize);// 0 - (isize -1)
		ids[j] = vecRank[idx];

		//
		vecRank.erase(vecRank.begin() + idx);
		isize -= 1;
	}
	//RandNum32List(minRankId, maxRankId, ids, ARENA_CHALL_LIST_NUM, myRankId);
}

uint32_t ArenaMgr::GetRankId(CharIDType charId)
{
	uint32_t rankId = MAX_ARENA_NUM + 1;

	MAP_UINT64_UINT32::iterator iter = _ranks.find(charId);
	if (iter != _ranks.end())
	{
		return iter->second;
	}

	//找不到排名的默认都是5000名以外的
	return rankId;
}

uint32_t ArenaMgr::GetRobotId(uint32_t rankId)
{
	if (rankId > MAX_ARENA_NUM)
	{
		rankId = MAX_ARENA_NUM;
	}

	ORDER_MAP_UINT32_UINT32::iterator iter = _robatConfigRanks.find(rankId);
	if (iter != _robatConfigRanks.end())
	{
		return iter->second;
	}

	return 0;
}

uint32_t ArenaMgr::GetRobotRankId(uint32_t robotId)
{
	uint32_t rankId = MAX_ARENA_NUM + 1;
	ORDER_MAP_UINT32_UINT32::iterator iter = _robatConfigIds.find(robotId);
	if (iter != _robatConfigIds.end())
	{
		return iter->second;
	}

	return rankId;
}

bool ArenaMgr::CanChall(CharIDType charId, uint32_t challRankId)
{
	if (challRankId <= 0)
	{
		return false;
	}

	uint32_t myRankId = GetRankId(charId);

	int32_t maxRankId = 0;
	int32_t minRankId = 0;

	//如果是大于5000外的
	if (myRankId > MAX_ARENA_NUM)
	{
		minRankId = MAX_ARENA_NUM - 1000;
		maxRankId = MAX_ARENA_NUM;
	}

	else if (myRankId >= 1 && myRankId <= 9)
	{
		int32_t intervalRankId = myRankId - 5;
		minRankId = intervalRankId <= 0 ? 1 : myRankId - 5;
		maxRankId = myRankId + 10;
	}

	else if (myRankId >= 10 && myRankId <= 19)
	{
		minRankId = myRankId - 5;
		maxRankId = myRankId + 10;
	}

	else if (myRankId >= 20 && myRankId <= 49)
	{
		minRankId = myRankId - 10;
		maxRankId = myRankId + 10;
	}

	else if (myRankId >= 50 && myRankId <= 99)
	{
		minRankId = myRankId - 30;
		maxRankId = myRankId + 20;
	}

	else if (myRankId >= 100 && myRankId <= 199)
	{
		minRankId = myRankId - 50;
		maxRankId = myRankId + 30;
	}

	else if (myRankId >= 200 && myRankId <= 499)
	{
		minRankId = myRankId - 100;
		maxRankId = myRankId + 50;
	}

	if (myRankId >= 500 && myRankId <= 999)
	{
		minRankId = myRankId - 300;
		maxRankId = myRankId + 100;
	}

	if (myRankId >= 1000 && myRankId <= 1999)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId + 200;
	}

	if (myRankId >= 2000 && myRankId <= 2999)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId;
	}

	if (myRankId >= 3000 && myRankId <= 3999)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId;
	}

	if (myRankId >= 4000 && myRankId <= 5000)
	{
		minRankId = myRankId - 500;
		maxRankId = myRankId;
	}

	if ((int32_t)challRankId >= minRankId && (int32_t)challRankId <= maxRankId)
	{
		return true;
	}

	return false;
}

void ArenaMgr::RemoveBeChallenged(CharIDType charId, ARENA_CHALLENGE_TYPE type)
{
	InArenaBeChallenged beChallenged;
	beChallenged.dstId = charId;
	beChallenged.type = type;
	InArenaBeChallengedMap::iterator iter = _beChallengedMap.find(beChallenged);
	if (iter != _beChallengedMap.end())
	{
		_beChallengedMap.erase(iter);
	}
}

bool ArenaMgr::ChangeChallRank(CharIDType srcId, CharIDType dstId, ARENA_CHALLENGE_TYPE type)
{
	if (type == ARENA_CHALLENGE_TYPE_ROBOT) //机器人
	{
		return ChangeRankByRobot(srcId, dstId);
	}

	return ChangeRank(srcId, dstId);
}

bool ArenaMgr::ChangeRank(CharIDType srcId, CharIDType dstId)
{
	uint32_t dstRankId = GetRankId(dstId);

	if (dstRankId > MAX_ARENA_NUM || dstRankId <= 0)
	{
		return false;
	}

	uint32_t oldRrank = MAX_ARENA_NUM + 1;
	MAP_UINT64_UINT32::const_iterator it = _ranks.find(srcId);
	if (it != _ranks.end())
	{
		oldRrank = it->second;
	}

	//如果胜利方的排名高于被挑战方的排名则排名不需要改变
	if (oldRrank <= dstRankId)
	{
		return false;
	}

	uint32_t index = oldRrank;
	if (index > MAX_ARENA_NUM)
	{ 
		//先移除挑战者排名
		_rankData[dstRankId] = 0;
		_ranks.erase(dstId);
		//新用户上榜
		_rankData[dstRankId] = srcId;
		_ranks[srcId] = dstRankId;
		AddNeedSave();
	}
	else
	{
		//dstid 排名设置为 index
		_rankData[index] = dstId;
		_ranks[dstId] = index;
		//srcid 排名设置为 dstRankId
		_rankData[dstRankId] = srcId;
		_ranks[srcId] = dstRankId;
		AddNeedSave();
	}

	return true;
}

bool ArenaMgr::ChangeRankByRobot(CharIDType srcId, uint32_t dstId)
{
	uint32_t dstRankId = GetRobotRankId(dstId);

	if (dstRankId > MAX_ARENA_NUM || dstRankId <= 0)
	{
		return false;
	}

	uint32_t oldRrank = MAX_ARENA_NUM + 1;
	MAP_UINT64_UINT32::const_iterator it = _ranks.find(srcId);
	if (it != _ranks.end())
	{
		oldRrank = it->second;
	}

	//如果胜利方的排名高于被挑战方的排名则排名不需要改变
	if (oldRrank <= dstRankId)
	{
		return false;
	}

	uint32_t index = oldRrank;
	if (index > MAX_ARENA_NUM)
	{ // 新用户上榜，直接做位置顶替
		_rankData[dstRankId] = srcId;
		_ranks[srcId] = dstRankId;
		AddNeedSave();
	}
	else
	{
		//清除原来的排名
		_rankData[index] = 0;
		//设置新的排名
		_rankData[dstRankId] = srcId;
		_ranks[srcId] = dstRankId;
		AddNeedSave();
	}

	return true;
}

void ArenaMgr::SendArenaWinMail(CharIDType srcId, CharIDType dstId)
{
	OfflineCharacterData *offlineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(srcId);
	if (nullptr == offlineCharacterData)
	{
		LogErrFmtPrint("ArenaMgr::SendArenaWinMail....nullptr == offlineCharacterData..srcid:%lu, destid:%lu ", srcId, dstId);
		return;
	}

	string strTopic = "竞技场防守胜利";
	char szContent[512] = {0};
	sprintf(szContent, "%s在竟技场中向你发起挑战，你将其轻松击退", offlineCharacterData->GetCharName());
	string strContent = szContent;
	LIST_ITEM lstItem;
	lstItem.clear();
	g_GetMailMgr()->SendSystemMail(dstId, strTopic, strContent, lstItem, 0, 0, 0, 0, 0);
}

void ArenaMgr::SendArenaLoseMail(CharIDType srcId, CharIDType dstId)
{
	OfflineCharacterData *offlineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(srcId);
	if (nullptr == offlineCharacterData)
	{
		LogErrFmtPrint("ArenaMgr::SendArenaLoseMail....nullptr == offlineCharacterData..srcid:%lu, destid:%lu ",srcId,dstId);
		return;
	}

	string strTopic = "竞技场防守失败";
	char szContent[2048] = {0};
	uint32_t dstRankId = GetRankId(dstId);
	if (dstRankId > MAX_ARENA_NUM)
	{
		sprintf(szContent, "%s在竟技场中击败了你，你掉出了榜外", offlineCharacterData->GetCharName());
	}
	else
	{
		sprintf(szContent, "%s在竟技场中击败了你，你的竞技排名降至%d", offlineCharacterData->GetCharName(), dstRankId);
	}
	string strContent = szContent;
	LIST_ITEM lstItem;
	lstItem.clear();

	g_GetMailMgr()->SendSystemMail(dstId, strTopic, strContent, lstItem, 0, 0, 0, 0, 0);
}

void ArenaMgr::SendArenaRewardMail()
{
	string strTopic = "竞技场排名奖励";
	char szContent[2048] = {'\0'};
	LIST_ITEM lstItem;
	uint32_t index = 0;
	MAP_UINT64_UINT32::iterator iterEvery = _mailEveryday.begin();
	while (iterEvery != _mailEveryday.end())
	{
		CharIDType charId = iterEvery->first;
		int32_t rank = iterEvery->second;
		const ArenaRankawardCfgInfo *rewardCfgInfo = GetArenaRankawardCfgInfo(rank);
		if (nullptr == rewardCfgInfo)
		{
			LogErrFmtPrint("[center]  ArenaMgr::SendArenaRewardMail....nullptr == rewardCfgInfo...rank:%d,cid:%lu ", rank,charId);
			iterEvery = _mailEveryday.erase(iterEvery);
			continue;
		}
		memset(szContent, 0, 2048);
		snprintf(szContent, 2047, "你在竞技场中排名%d，这是你当前的排名奖励，请查收！", rank);
		string strContent = szContent;
		lstItem.clear();
		for (uint32_t i = 0; i < rewardCfgInfo->vecArenaRankawardRewardCfg.size(); i++)
		{
			SItem item;
			item.nItemID = rewardCfgInfo->vecArenaRankawardRewardCfg[i].ID;
			item.nNum = rewardCfgInfo->vecArenaRankawardRewardCfg[i].Value;
			if (item.nItemID > 0 && item.nNum > 0)
			{
				lstItem.push_back(item);
			}
		}
		//奖励非绑定金币 绑定钻石 竞技场积分
		if (!g_GetMailMgr()->SendSystemMail(charId, strTopic, strContent, lstItem, rewardCfgInfo->RewardGold, 0, 0, rewardCfgInfo->RewardDia, rewardCfgInfo->RewardPoint))
		{
			MMOLOG_FMT_ERROR("ArenaMgr::SendArenaRewardMail...SendSystemMail failed...charid:%lu, rank:%d ", charId,rank);
		}
		else
		{
			LogInfoFmtPrint("[center] ArenaMgr::SendArenaRewardMail sucess...charid:%lu,rank:%d ", charId, rank);
		}
		
		//移除已发送的玩家
		iterEvery =	_mailEveryday.erase(iterEvery);
		//
		++index;
		if (index >= 200) //每间隔5s发200封邮件
		{
			if (_mailEveryday.size() > 0)
			{
				LogErrFmtPrint("[center] SendArenaRewardMail...continue send mail...count:%d ", (int32_t)_mailEveryday.size());
				//5秒后发送另外500名邮件
				g_GetTimerAxis()->KillTimer(TIMER_ID_StartLoad_ArenaRewardMailInterval, this);
				g_GetTimerAxis()->SetTimer(TIMER_ID_StartLoad_ArenaRewardMailInterval, 5 * 1000, this, 1);
				break;
			}			
		} // end of if (index >= 200) 
	} // end of while (iterEvery != _mailEveryday.end())
}

const ArenaRankawardCfgInfo *ArenaMgr::GetArenaRankawardCfgInfo(uint32_t rankId)
{
	const ArenaRankawardCfgMap *pCfgMap = g_GetArenaRankawardCfgTable()->GetArenaRankawardCfgMap();
	if (nullptr != pCfgMap)
	{
		ArenaRankawardCfgMap::const_iterator iter = pCfgMap->begin();
		for (; iter != pCfgMap->end(); ++iter)
		{
			const ArenaRankawardCfgInfo &info = iter->second;
			if ((int32_t)rankId >= info.arenaDown && (int32_t)rankId <= info.arenaUp)
			{
				return &info;
			}
		}
	}

	return nullptr;
}
//增加保存标志
void ArenaMgr::AddNeedSave()
{
	m_needSave = true;
}

int32_t ArenaMgr::GetBestReward(uint32_t oldRankId, uint32_t newRankId)
{
	float total = 0;

	if (newRankId >= oldRankId)
	{
		return total;
	}

	if (oldRankId >= MAX_ARENA_NUM + 1)
	{
		oldRankId = MAX_ARENA_NUM;
	}

	for (uint32_t i = oldRankId; (i >= 1 && i != newRankId); i--)
	{
		if (i >= 1000 && i <= 5000)
		{
			total += 0.1f;
		}
		else if (i >= 500 && i <= 999)
		{
			total += 1;
		}
		else if (i >= 100 && i <= 499)
		{
			total += 1.5f;
		}
		else if (i >= 50 && i <= 99)
		{
			total += 20;
		}
		else if (i >= 20 && i <= 49)
		{
			total += 50;
		}
		else if (i >= 10 && i <= 19)
		{
			total += 200;
		}
		else if (i >= 1 && i <= 9)
		{
			total += 300;
		}
	}

	return ceil(total);
}